﻿#include "DXUT.h"
#include "FXShaderEffect.h"
#include "SDKmisc.h"
 #include <stdarg.h>
CFXShaderEffect::~CFXShaderEffect(void)
{
}

void CFXShaderEffect::InitParametersHandle()
{
	//Matrix
 
	m_world=m_pEffect->GetParameterBySemantic(0,"WORLD");
	m_view=m_pEffect->GetParameterBySemantic(0,"VIEW");
	m_proj=m_pEffect->GetParameterBySemantic(0,"PROJECTION");

	m_worldView=m_pEffect->GetParameterBySemantic(0,"WORLDVIEW ");
	m_worldViewProj=m_pEffect->GetParameterBySemantic(0,"WORLDVIEWPROJECTION");
	m_viewProj=m_pEffect->GetParameterBySemantic(0,"VIEWPROJECTION");
	m_worldViewInverse=m_pEffect->GetParameterBySemantic(0,"WORLDVIEWINVERSE");
	m_viewInverse=m_pEffect->GetParameterBySemantic(0,"VIEWINVERSE");

	//D3DXVECTOR4

	m_lightDir=m_pEffect->GetParameterBySemantic(0,"DIRECTION");
	m_ambientColor=m_pEffect->GetParameterBySemantic(0,"AMBIENT");
	m_diffuseColor=m_pEffect->GetParameterBySemantic(0,"DIFFUSE");
	m_specularColor=m_pEffect->GetParameterBySemantic(0,"SPECULAR");

	//float
	m_shininess=m_pEffect->GetParameterBySemantic(0,"SPECULARPOWER");

	//Texture
	m_diffuseTexture=m_pEffect->GetParameterBySemantic(0,"DIFFUSEMAP");
	m_normalTexture=m_pEffect->GetParameterBySemantic(0,"NORMAL");
	m_heightTexture=m_pEffect->GetParameterBySemantic(0,"HEIGHT");
	m_cubeTexture=m_pEffect->GetParameterBySemantic(0,"ENVIRONMENT");
}

void CFXShaderEffect::ResetParameters()
{
 
		m_lastView=
		m_lastProj=
		m_lastWorldView=
		m_lastWorldViewProj=
		m_lastViewProj=
		m_lastWorldViewInverse=
		m_lastViewInverse=
		m_lastWorld=D3DXMATRIX();

	  m_lastLightDir=D3DXVECTOR4(0,0,0,0);
	   m_lastAmbientColor=m_lastDiffuseColor=m_lastSpecularColor=D3DXCOLOR(-1,-1,-1,-1);
    m_lastShininess=0.0f;
	  m_lastDiffseTexture=m_lastNormalTexture=m_lastHeightTexture=0;

       m_lastCubeTexture=0;
	
}

CFXShaderEffect::CFXShaderEffect( const TCHAR * resName,const TCHAR * szFilePath, D3DPOOL pool/*=D3DPOOL_DEFAULT*/ )
	:CGraphicsFileResource(RESOURCE_TYPE_FXSHADEREFFECT,resName,szFilePath,pool)
	 
{



	m_world=NULL;
	m_view=NULL;
	m_proj=NULL;

	m_worldView=NULL;
	m_worldViewProj=NULL;
	m_viewProj=NULL;
	m_worldViewInverse=NULL;
	m_viewInverse=NULL;

	//D3DXVECTOR4

	m_lightDir=NULL;
	m_ambientColor=NULL;
	m_diffuseColor=NULL;
	m_specularColor=NULL;

	//float
	m_shininess=NULL;

	//Texture
	m_diffuseTexture=NULL;
	m_normalTexture=NULL;
	m_heightTexture=NULL;
	m_cubeTexture=NULL;
	 this->ResetParameters();
}

HRESULT CFXShaderEffect::OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice )
{

	HRESULT hr;
	WCHAR wszPath[MAX_PATH];

	 V_RETURN(  DXUTFindDXSDKMediaFileCch( wszPath, MAX_PATH, this->GetFileName() ) ) ;


	LPD3DXBUFFER  pError;
	hr = D3DXCreateEffectFromFile( pd3dDevice,
		wszPath,
		NULL,
		NULL,
	       0,
		0,
		&m_pEffect,
		&pError );

	if( FAILED(hr))
	{

		MessageBoxA(0,(char*)pError->GetBufferPointer(),0,0);
		pError->Release();
		return hr;

	}


	hr = m_pEffect->FindNextValidTechnique(NULL, &m_hTechnique);
	if( FAILED( hr ) )
	{
		DXTRACE_ERR_MSGBOX(DXGetErrorString(hr),hr);
		SAFE_RELEASE(m_pEffect);
		return hr;
	}
    V_RETURN(m_pEffect->SetTechnique(m_hTechnique) );
 
	this->InitParametersHandle();
	return hr;

}

void CFXShaderEffect::OnD3D9DestroyDevice()
{
	SAFE_RELEASE( m_pEffect);
}

HRESULT CFXShaderEffect::OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice )
{
	return m_pEffect->OnResetDevice();

}

void CFXShaderEffect::OnD3D9LostDevice()
{
	m_pEffect->OnLostDevice();

}

inline LPD3DXEFFECT CFXShaderEffect::GetEffect()
{
	return m_pEffect;
}

void CFXShaderEffect::SetWorldMatrix( const D3DXMATRIX & matWorld )
{
	if(m_world==NULL ||m_lastWorld==matWorld)
		return;

	m_pEffect->SetMatrix(m_world,&matWorld);
	m_lastWorld=matWorld;

}

void CFXShaderEffect::SetViewMatrix( const D3DXMATRIX & matView )
{

	if( m_view==NULL || m_lastView==matView)
		return;

	m_pEffect->SetMatrix(m_view,&matView);
	m_lastView=matView;
}

void CFXShaderEffect::SetProjMatrix( const D3DXMATRIX & matProj )
{
	if(m_proj==NULL ||m_lastProj==matProj)
		return;

	m_pEffect->SetMatrix(m_proj,&matProj);
	m_lastProj=matProj;
}

void CFXShaderEffect::SetWorldViewMatrix( const D3DXMATRIX & matWorldView )
{

	if(m_worldView==NULL || m_lastWorldView==matWorldView)
		return;

	m_pEffect->SetMatrix(m_worldView,&matWorldView);
	m_lastWorldView=matWorldView;
}

void CFXShaderEffect::SetWorldViewProjMatrix( const D3DXMATRIX & matWorldViewProj )
{
	if(m_worldViewProj==NULL ||m_lastWorldViewProj==matWorldViewProj)
		return;

	m_pEffect->SetMatrix(m_worldViewProj,&matWorldViewProj);
	m_lastWorldViewProj=matWorldViewProj;
}

void CFXShaderEffect::SetViewProjMatrix( const D3DXMATRIX & matViewProj )
{
	if(m_viewProj==NULL ||m_lastViewProj==matViewProj)
		return;

	m_pEffect->SetMatrix(m_viewProj,&matViewProj);
	m_lastViewProj=matViewProj;
}

void CFXShaderEffect::SetWorldViewInverseMatrix( const D3DXMATRIX & matWorldViewInverse )
{
	if(m_worldViewInverse==NULL ||m_lastWorldViewInverse==matWorldViewInverse)
		return;

	m_pEffect->SetMatrix(m_worldViewInverse,&matWorldViewInverse);
	m_lastWorldViewInverse=matWorldViewInverse;
}

void CFXShaderEffect::SetViewInverseMatrix( const D3DXMATRIX & matViewInverse )
{
	if( m_viewInverse==NULL ||m_lastViewInverse==matViewInverse)
		return;

	m_pEffect->SetMatrix(m_viewInverse,&matViewInverse);
	m_lastViewInverse=matViewInverse;
}

void CFXShaderEffect::SetLightDir( const D3DXVECTOR4 & vecLightDir )
{
	if(m_lightDir==NULL ||  m_lastLightDir==vecLightDir)
		return ;
	m_pEffect->SetVector(m_lightDir,&vecLightDir);
	m_lastLightDir=vecLightDir;

}

void CFXShaderEffect::SetAmbientColor( const D3DXCOLOR & AmbientColor )
{
	if(m_ambientColor==NULL ||  m_lastAmbientColor==AmbientColor)
		return ;
 
m_pEffect->SetFloatArray(m_ambientColor,(float *)&AmbientColor,4);
	m_lastAmbientColor=AmbientColor;

}

void CFXShaderEffect::SetDiffuseColor( const D3DXCOLOR & DiffuseColor )
{
	if(  (m_diffuseColor==NULL)||  (m_lastDiffuseColor==DiffuseColor))
		return ;
	m_pEffect->SetFloatArray(m_diffuseColor,(float *)&DiffuseColor,4);
	m_lastDiffuseColor=DiffuseColor;
}

void CFXShaderEffect::SetSpecularColor( const D3DXCOLOR & SpecularColor )
{
	if( (m_specularColor==NULL)|| (m_lastSpecularColor==SpecularColor))
		return ;
 
 	m_pEffect->SetFloatArray(m_specularColor,(float *)&SpecularColor,4);
	m_lastSpecularColor=SpecularColor;
}

void CFXShaderEffect:: SetSpecularPower(const  float & shininess)
{
 
	if( (m_shininess==NULL)|| (m_lastShininess==shininess))
		return ;
	m_pEffect->SetFloat(m_shininess,shininess);
	m_lastShininess=shininess;
}

void CFXShaderEffect::SetDiffseTexture( LPDIRECT3DBASETEXTURE9 pDiffuseTexture )
{
 

	if( (m_diffuseTexture==NULL)|| (m_lastDiffseTexture==pDiffuseTexture))
		return ;

	m_pEffect->SetTexture(m_diffuseTexture,pDiffuseTexture);
	m_lastDiffseTexture=pDiffuseTexture;
}

void CFXShaderEffect::SetNormalTexture( LPDIRECT3DBASETEXTURE9 pNormalTexture )
{
	if( (m_normalTexture==NULL)|| (m_lastNormalTexture==pNormalTexture))
		return ;
	m_pEffect->SetTexture(m_normalTexture,pNormalTexture);
	m_lastNormalTexture=pNormalTexture;
}

void CFXShaderEffect::SetHeightTexture( LPDIRECT3DBASETEXTURE9 pHeightTexutre )
{
	if( (m_heightTexture==NULL)|| (m_lastHeightTexture==pHeightTexutre))
		return ;
	m_pEffect->SetTexture(m_heightTexture,pHeightTexutre);
	m_lastHeightTexture=pHeightTexutre;
}

void CFXShaderEffect::SetCubeTexure( LPDIRECT3DBASETEXTURE9 pCubeTexture )
{


		if ((m_cubeTexture==NULL)||(m_lastCubeTexture==pCubeTexture))
			return ;
	m_pEffect->SetTexture(m_cubeTexture,pCubeTexture);
	m_lastCubeTexture=pCubeTexture;
}

void CFXShaderEffect::Render( LPCSTR tn,int n,...)
{

	va_list ap;
	va_start ( ap, n );
	UINT iPass;
	D3DXHANDLE   pHt=m_pEffect->GetTechniqueByName(tn); 
	assert(pHt);
	m_pEffect->SetTechnique(tn);
	m_pEffect->Begin(&iPass,0);
	for(int j=0; j<iPass;j++)
	{

		m_pEffect->BeginPass(j);
		for ( int i= 0; i< n; i++ )
		{
			IRenderable* r = va_arg (ap, IRenderable*);
			if (r   )
			{
				r->OnD3D9FrameRender(0);

			}
		}
		m_pEffect->EndPass();
	}
	m_pEffect->End();

}

void CFXShaderEffect::Render( IRenderable * pRenderable )
{
	assert(pRenderable); 
	UINT iPass;

	m_pEffect->Begin(&iPass,0);
	for(int j=0; j<iPass;j++)
	{

		m_pEffect->BeginPass(j);

		pRenderable->OnD3D9FrameRender(0);
		m_pEffect->EndPass();

	}

	m_pEffect->End();
}
 



  